package com.asen.commons.core.jdbc.param;

import com.asen.commons.core.jdbc.handler.TypeHandler;
import com.asen.commons.core.jdbc.handler.TypeHandlerHolder;
import com.asen.commons.utils.BaseAssert;
import org.springframework.jdbc.core.PreparedStatementSetter;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * JDBC参数适配器
 *
 * @author Gary
 * @version 1.0
 * @date 2018-11-16
 */
public class ParamStatementSetter implements PreparedStatementSetter {

    private List<ParamObject> paramList = new ArrayList<ParamObject>();

    /**
     * 设置Object类型参数.
     *
     * @param value
     */
    public void setParam(Object value) {
        setParam(value.getClass(), value);
    }

    /**
     * 设置参数
     *
     * @param javaType
     * @param value
     */
    public void setParam(Class<?> javaType, Object value) {
        setParam(javaType, value, TypeHandlerHolder.getHandler(javaType));
    }

    /**
     * 设置参数
     *
     * @param javaType
     * @param value
     * @param handler
     */
    public void setParam(Class<?> javaType, Object value, TypeHandler handler) {
        checkIfNull(javaType);
        ParamObject paramObject = new ParamObject(javaType, value, handler);
        paramList.add(paramObject);
    }

    /**
     * 设置空值
     *
     * @param javaType
     */
    public void setNull(Class<?> javaType) {
        checkIfNull(javaType);
        ParamObject paramObject = new ParamObject(javaType);
        paramList.add(paramObject);
    }

    public void setNull(Class<?> javaType, TypeHandler handler) {
        checkIfNull(javaType);
        ParamObject paramObject = new ParamObject(javaType, null, handler);
        paramList.add(paramObject);
    }

    /**
     * 参数空值检查
     *
     * @param value
     */
    private void checkIfNull(Object value) {
        BaseAssert.notNull(value, "参数不能为空");
    }

    /**
     * 获取参数值
     *
     * @param i
     * @return
     */
    public Object getParamValue(int i) {
        return paramList.get(i).getValue();
    }

    /**
     * 获取参数类型
     *
     * @param i
     * @return
     */
    public Class<?> getParamType(int i) {
        return paramList.get(i).getJavaType();
    }

    /**
     * 参数列表大小.
     *
     * @return
     */
    public int size() {
        return paramList.size();
    }

    public List<ParamObject> getParamList() {
        return paramList;
    }

    public ParamObject getParam(int i) {
        return paramList.get(i);
    }

    @Override
    public void setValues(PreparedStatement ps) throws SQLException {
        try {
            for (int i = 0; i < paramList.size(); i++) {
                doSetValue(ps, i + 1, paramList.get(i));
            }
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }

    private void doSetValue(PreparedStatement ps, int pos, ParamObject param) throws Exception {

        Object value = param.getValue();

        TypeHandler handler = param.getHandler();
        if (handler == null) {
            handler = TypeHandlerHolder.getHandler(param.getJavaType());
        }

        handler.setParameter(ps, pos, value);
    }

    public boolean isEmpty() {
        return paramList.isEmpty();
    }

    @Override
    public String toString() {
        return "ParamStatementSetter{" +
                "paramList=" + paramList +
                '}';
    }
}
